﻿using System;
using System.Net;
using System.Windows;
using System.Collections.Generic;
using Microsoft.Phone.BackgroundTransfer;
using System.Linq;
using System.IO.IsolatedStorage;
using System.IO;
using PhotoUploader.Common;
using System.Collections.ObjectModel;
using PhotoUploader.Models;
using KuuCarPivot;

namespace PhotoUploader.Services
{
    public class UploadService
    {
        public static string ServiceUploadLocationURL = "http://192.168.0.112/Shop/UserAddShopPicture"; 
        private const string TransfersFiles = @"\shared\transfers";
        //private bool _wifiOnly = true;
        //private bool _externalPowerOnly = true;
        private bool _wifiOnly = false;
        private bool _externalPowerOnly = false;
        private bool _waitingForExternalPower;
        private bool _waitingForExternalPowerDueToBatterySaverMode;
        private bool _waitingForNonVoiceBlockingNetwork;
        private bool _waitingForWiFi; 
        public IEnumerable<BackgroundTransferRequest> TransferRequests { get; private set; }
        public UploadService()
        {
            EnsureTransfersFolder();
        }
        private void EnsureTransfersFolder()
        {
            using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (!isoStore.DirectoryExists(TransfersFiles))
                {
                    isoStore.CreateDirectory(TransfersFiles);
                }
            }
        }
        public void RefreshTransfers()
        {
            _waitingForExternalPower = false;
            _waitingForExternalPowerDueToBatterySaverMode = false;
            _waitingForNonVoiceBlockingNetwork = false;
            _waitingForWiFi = false;

            InitialTansferStatusCheck();
            UpdateRequestsList();
        }

        private void InitialTansferStatusCheck()
        {
            UpdateRequestsList();

            foreach (var transfer in TransferRequests)
            {
                transfer.TransferStatusChanged += OnTransferStatusChanged;
                transfer.TransferProgressChanged += OnTransferProgressChanged;
                ProcessTransfer(transfer);
            }

            if (_waitingForExternalPower)
            {
                MessageBox.Show("Connect your device to external power to continue uploading files.");
            }
            if (_waitingForExternalPowerDueToBatterySaverMode)
            {
                MessageBox.Show("Connect your device to external power or disable Battery Saver Mode to continue uploading files.");
            }
            if (_waitingForNonVoiceBlockingNetwork)
            {
                MessageBox.Show("Connect your device to network with simultaneous voice and data to continue uploading files.");
            }
            if (_waitingForWiFi)
            {
                MessageBox.Show("Connect your device to a WiFi network to continue uploading files.");
            }
        }

        private void OnTransferStatusChanged(object sender, BackgroundTransferEventArgs e)
        {
            ProcessTransfer(e.Request);
            UpdateRequestsList();
        }

        private void ProcessTransfer(BackgroundTransferRequest transfer)
        {
            switch (transfer.TransferStatus)
            {
                case TransferStatus.Completed:

                    if (transfer.StatusCode == 200 || transfer.StatusCode == 206)
                    {
                        var requestId = transfer.RequestId;
                        RemoveTransferRequest(requestId);
                        Picture picture=PictureRepository.Instance.Pictures.Where(p => p.RequestId == requestId).FirstOrDefault();
                        if (picture!=null)
                        {
                            picture.IsUploaded = true;
                        }
                        PictureRepository.Instance.SavePicture(picture);
                        PictureRepository.Instance.RemovePicture(requestId);
                        using (var iso = IsolatedStorageFile.GetUserStoreForApplication())
                        {
                            if (iso.FileExists(transfer.UploadLocation.OriginalString))
                                iso.DeleteFile(transfer.UploadLocation.OriginalString);
                            PictureRepository.Instance.RemovePicture(picture);
                        }
                        Deployment.Current.Dispatcher.BeginInvoke(delegate
                        {
                            MessageBox.Show("图片上传成功，谢谢您的分享!可继续添加图片.");
                        });
                     
                    }
                    else
                    {
                        RemoveTransferRequest(transfer.RequestId);                        

                        if (transfer.TransferError != null)
                        {
                        }
                    }
                    break;

                case TransferStatus.WaitingForExternalPower:
                    _waitingForExternalPower = true;
                    Deployment.Current.Dispatcher.BeginInvoke(delegate {
                        MessageBox.Show("_waitingForExternalPower = true");
                    });
                    break;

                case TransferStatus.WaitingForExternalPowerDueToBatterySaverMode:
                    _waitingForExternalPowerDueToBatterySaverMode = true;
                    Deployment.Current.Dispatcher.BeginInvoke(delegate
                    {
                        MessageBox.Show(" _waitingForExternalPowerDueToBatterySaverMode = true");
                    });
                    break;

                case TransferStatus.WaitingForNonVoiceBlockingNetwork:
                    _waitingForNonVoiceBlockingNetwork = true;
                    Deployment.Current.Dispatcher.BeginInvoke(delegate
                    {
                        MessageBox.Show(" _waitingForNonVoiceBlockingNetwork = true");
                    });
                    break;

                case TransferStatus.WaitingForWiFi:
                    _waitingForWiFi = true;
                    Deployment.Current.Dispatcher.BeginInvoke(delegate
                    {
                        MessageBox.Show(" _waitingForWiFi = true");
                    });
                    break;
            }
        }

        private void OnTransferProgressChanged(object sender, BackgroundTransferEventArgs e)
        {
            UpdateRequestsList();
        }

        private void UpdateRequestsList()
        {
            if (TransferRequests != null)
            {
                foreach (var request in TransferRequests)
                {
                    request.Dispose();
                }
            }
            TransferRequests = BackgroundTransferService.Requests;

            foreach (var tr in TransferRequests)
                PictureRepository.Instance.UpdatePicture(tr.RequestId, tr.TransferStatus, tr.BytesSent, tr.TotalBytesToSend);            
        }

        private void RemoveTransferRequest(string requestId)
        {
            var transferToRemove = BackgroundTransferService.Find(requestId);

            if (transferToRemove == null) return;

            try
            {
                BackgroundTransferService.Remove(transferToRemove);
            }
            catch (Exception)
            {

            }
        }

        public void CancelUpload(Picture picture)
        {
            RemoveTransferRequest(picture.RequestId);

            PictureRepository.Instance.SetPictureStatus(picture, FileStatus.New, picture.RequestId);

            UpdateRequestsList();
        }

        public void StartUpload(Picture picture)
        {
            if (BackgroundTransferService.Requests.Count() <5)
            {
                AddBackgroundTransfer(picture);
            }
            else
            {
                MessageBox.Show("The maximum number of background file transfer requests for this application has been exceeded.");
                foreach (var item in BackgroundTransferService.Requests)
                {
                    BackgroundTransferService.Remove(item);
                }
              
            }          
        }

        private void AddBackgroundTransfer(Picture picture)
        {
            IsolatedStorageFileExtensions.SavePicture(Path.Combine(TransfersFiles, picture.FileName), picture.Data);

            var transferRequest = new BackgroundTransferRequest(new Uri(ServiceUploadLocationURL, UriKind.Absolute));

            if (!_wifiOnly)
            {
                transferRequest.TransferPreferences = TransferPreferences.AllowCellular;
            }
            if (!_externalPowerOnly)
            {
                transferRequest.TransferPreferences = TransferPreferences.AllowBattery;
            }
            if (!_wifiOnly && !_externalPowerOnly)
            {
                transferRequest.TransferPreferences = TransferPreferences.AllowCellularAndBattery;
            }
            transferRequest.Method = "POST";
            transferRequest.UploadLocation = new Uri(TransfersFiles + @"\" + picture.FileName, UriKind.Relative);
            
            transferRequest.TransferStatusChanged += OnTransferStatusChanged;
            transferRequest.TransferProgressChanged += OnTransferProgressChanged;
            try
            {                
                BackgroundTransferService.Add(transferRequest);
                PictureRepository.Instance.SetPictureStatus(picture, FileStatus.Active, transferRequest.RequestId);
                UpdateRequestsList();
            }
            catch (InvalidOperationException ex)
            {
                MessageBox.Show("Unable to add background transfer request. " + ex.Message);
            }
            catch (Exception)
            {
                MessageBox.Show("Unable to add background transfer request.");
            }
        }
        public static readonly UploadService Instance = new UploadService();
    }
}
